/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * 知启蒙Servlet兼容库（zhiqim_servlet）在LGPL3.0协议下开源：https://www.zhiqim.com/gitcan/zhiqim/zhiqim_servlet.htm
 *
 * This file is part of [zhiqim_servlet].
 * 
 * [zhiqim_servlet] is free software: you can redistribute
 * it and/or modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * [zhiqim_servlet] is distributed in the hope that it will
 * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with [zhiqim_servlet].
 * If not, see <http://www.gnu.org/licenses/>.
 */
package org.zhiqim.servlet;

import java.util.Enumeration;
import java.util.List;

import javax.servlet.http.HttpSession;

import org.zhiqim.kernel.extend.HashMapSO;
import org.zhiqim.httpd.HttpContext;
import org.zhiqim.httpd.HttpSessionUser;
import org.zhiqim.httpd.HttpWebsocketConnection;
import org.zhiqim.httpd.HttpdConstants;
import org.zhiqim.kernel.util.Asserts;
import org.zhiqim.kernel.util.DateTimes;
import org.zhiqim.kernel.util.Ints;
import org.zhiqim.kernel.util.Longs;
import org.zhiqim.kernel.util.Strings;

/**
 * ZML会话封装
 *
 * @version v1.0.0 @author zhichenggang 2017-1-7 新建与整理
 */
public class ZmlSession implements org.zhiqim.httpd.HttpSession, HttpdConstants
{
    private final HttpContext context;
    private final HttpSession session;
    
    public ZmlSession(HttpContext context, HttpSession session)
    {
        this.context = context;
        this.session = session;
    }
    
    /************************************************************************************/
    //会话参数设置（最后访问时间、IP地址等） & 会话主动失效调用
    /************************************************************************************/
    
    @Override
    public void setMaxInactiveInterval(int maxInactiveInterval)
    {
        session.setMaxInactiveInterval(maxInactiveInterval);
    }
    
    @Override
    public void setSessionIp(String sessionIp)
    {
        if (session.getAttribute(_HTTP_SESSION_IP_) == null)
            session.setAttribute(_HTTP_SESSION_IP_, sessionIp);
    }
    
    @Override
    public void setUserAgent(String userAgent)
    {
        if (session.getAttribute(_HTTP_SESSION_UA_) == null)
            session.setAttribute(_HTTP_SESSION_UA_, userAgent);
    }
    
    @Override
    public void setLastAccessed()
    {//不需要处理，由容器自行处理
    }

    @Override
    public void invalidate()
    {
        session.invalidate();
    }
    
    
    /***********************************************************************/
    //浸入式修改会话编号，在Servlet容器中禁止调用
    /***********************************************************************/

    @Override
    public void setNewSessionId(String newSessionId)
    {
        throw Asserts.exception("该方法禁止在Servlet容器中调用，因为获取不到会话管理权限");
    }
    
    @Override
    public String getOldSessionId()
    {
        throw Asserts.exception("该方法禁止在Servlet容器中调用，因为获取不到会话管理权限");
    }

    @Override
    public void clearOldSessionId()
    {
        throw Asserts.exception("该方法禁止在Servlet容器中调用，因为获取不到会话管理权限");
    }
    
    /************************************************************************************/
    //实现方法
    /************************************************************************************/
    
    @Override
    public HttpContext getContext()
    {
        return context;
    }
    
    @Override
    public String getId()
    {
        return session.getId();
    }
    
    @Override
    public boolean isNew()
    {
        return session.isNew();
    }
    
    @Override
    public String getSessionIp()
    {
        return (String)session.getAttribute(_HTTP_SESSION_IP_);
    }
    
    public String getUserAgent()
    {
        return (String)session.getAttribute(_HTTP_SESSION_UA_);
    }
    
    @Override
    public int getMaxInactiveInterval()
    {
        return session.getMaxInactiveInterval();
    }
    
    @Override
    public long getCreated()
    {
        return session.getCreationTime();
    }
    
    @Override
    public String getCreateTime()
    {
        return DateTimes.toDateTimeString(session.getCreationTime());
    }
    
    @Override
    public long getLastAccessed()
    {
        return session.getLastAccessedTime();
    }
    
    @Override
    public String getLastAccessTime()
    {
        return DateTimes.toDateTimeString(session.getLastAccessedTime());
    }
    
    @Override
    public long getRemainSecond()
    {
        long remain = System.currentTimeMillis() - getLastAccessed();
        return session.getMaxInactiveInterval() - remain / 1000;
    }
    
    @Override
    public long getRemainMinute()
    {
        return getRemainSecond() / 60;
    }
    
    @Override
    public long[] getRemainTime()
    {
        long time = getRemainSecond();
        long day = time / 86400;
        long hour = time % 86400 / 3600;
        long minute = time % 3600 / 60;
        long second = time % 60;
        
        return new long[]{day, hour, minute, second};
    }
    
    @Override
    public String getRemainTimeDesc()
    {
        long[] times = getRemainTime();
        
        StringBuilder strb = new StringBuilder();
        if (times[0] > 0)
            strb.append(times[0]).append("天");
        if (times[1] > 0)
            strb.append(times[1]).append("小时");
        if (times[2] > 0)
            strb.append(times[2]).append("分");
        strb.append(times[3]).append("秒");
        
        return strb.toString();
    }
    
    /**********************************************/
    //SessionUser相关
    /**********************************************/    
    
    @Override/** 绑定会话用户信息 */
    public void bindSessionUser(HttpSessionUser sessionUser)
    {
        sessionUser.setSession(this);
        session.setAttribute(_HTTP_SESSION_USER_, sessionUser);
    }
    
    @Override/** 解绑会话用户信息 */
    public <T extends HttpSessionUser> void unbindSessionUser(Class<T> clazz)
    {
        session.removeAttribute(_HTTP_SESSION_USER_);
    }
    
    @Override/** 判断会话中是否有用户信息 */
    public boolean hasSessionUser()
    {
        return session.getAttribute(_HTTP_SESSION_USER_) != null;
    }
    
    @Override/** 判断会话中是否有用户信息且指定的用户类 */
    public <T extends HttpSessionUser> boolean hasSessionUser(Class<T> clazz)
    {
        Object obj = session.getAttribute(_HTTP_SESSION_USER_);
        return obj != null && obj.getClass() == clazz;
    }
    
    @Override
    public HttpSessionUser getSessionUser()
    {
        return (HttpSessionUser)session.getAttribute(_HTTP_SESSION_USER_);
    }

    @Override
    public String getSessionName()
    {
        HttpSessionUser sessionUser = (HttpSessionUser)session.getAttribute(_HTTP_SESSION_USER_);
        return sessionUser == null?null:sessionUser.getSessionName();
    }
    
    /** 获取会话用户信息且指定的用户类 */
    @Override @SuppressWarnings("unchecked")
    public <T extends HttpSessionUser> T getSessionUser(Class<T> clazz)
    {
        Object obj = session.getAttribute(_HTTP_SESSION_USER_);
        return obj == null?null:(obj.getClass() != clazz?null:(T)obj);
    }
    
    @Override/** 获取会话用户名称 */
    public <T extends HttpSessionUser> String getSessionName(Class<T> clazz)
    {
        HttpSessionUser sessionUser = (HttpSessionUser)session.getAttribute(_HTTP_SESSION_USER_);
        return sessionUser == null?null:sessionUser.getSessionName();
    }
    
    /*************************************************************************/
    //会话中的属性相关
    /*************************************************************************/
    
    @Override/** 设置属性 */
    public void setAttribute(String name, Object value)
    {
        session.setAttribute(name, value);
    }
    
    @Override/** 是否有属性 */
    public boolean hasAttribute(String name)
    {
        return session.getAttribute(name) != null;
    }
    
    @Override/** 删除属性 */
    public Object removeAttribute(String name)
    {
        Object value = session.getAttribute(name);
        session.removeAttribute(name);
        return value;
    }

    @Override/** 获取属性表 */
    public HashMapSO getAttributes()
    {
        HashMapSO attributeMap = new HashMapSO();
        Enumeration<String> enums = session.getAttributeNames();
        while (enums.hasMoreElements())
        {
            String key = enums.nextElement();
            attributeMap.put(key, attributeMap.get(key));
        }
        return attributeMap;
    }
    
    @Override/** 获取属性 */
    public Object getAttribute(String name)
    {
        return session.getAttribute(name);
    }
    
    @Override/** 获取属性 */
    public Object getAttribute(String name, Object defaultValue)
    {
        Object obj = session.getAttribute(name);
        return (obj == null)?defaultValue:obj;
    }
    
    @Override/** 获取属性字符串 */
    public String getAttributeString(String name)
    {
        return Strings.toString(getAttribute(name), null);
    }
    
    @Override/** 获取属性字符串 */
    public String getAttributeString(String name, String defaultValue)
    {
        return Strings.toString(getAttribute(name), defaultValue);
    }
    
    @Override/** 获取属性整型 */
    public int getAttributeInt(String name)
    {
        return getAttributeInt(name, -1);
    }
    
    @Override/** 获取属性整型 */
    public int getAttributeInt(String name, int defaultValue)
    {
        Object obj = getAttribute(name);
        if (obj == null)
            return defaultValue;
        else if (obj instanceof Integer)
            return (Integer)obj;
        else if (obj instanceof String)
            return Ints.toInt(obj, defaultValue);
        else
            return defaultValue;
    }
    
    @Override/** 获取属性长整型 */
    public long getAttributeLong(String name)
    {
        return getAttributeLong(name, -1);
    }
    
    @Override/** 获取属性长整型 */
    public long getAttributeLong(String name, long defaultValue)
    {
        Object obj = getAttribute(name);
        if (obj == null)
            return defaultValue;
        else if (obj instanceof Integer)
            return (Integer)obj;
        else if (obj instanceof Long)
            return (Long)obj;
        else if (obj instanceof String)
            return Longs.toLong(obj, defaultValue);
        else
            return defaultValue;
    }
    
    @Override/** 获取属性布尔型 */
    public boolean getAttributeBoolean(String name, boolean defaultValue)
    {
        Object obj = getAttribute(name);
        if (obj == null)
            return defaultValue;
        else if (obj instanceof Boolean)
            return (Boolean)obj;
        else if (obj instanceof String)
            return "true".equalsIgnoreCase((String)obj);
        else
            return defaultValue;
    }
    
    /************************************************************************************/
    //websocket不支持
    /************************************************************************************/

    @Override
    public List<HttpWebsocketConnection> getWebsocketConnection(String protocol)
    {
        return null;
    }

    @Override
    public void addWebsocketConnection(String protocol, HttpWebsocketConnection conn)
    {
    }

    @Override
    public void removeWebsocketConnection(String protocol, HttpWebsocketConnection conn)
    {
    }
}
